Appearance
SpringMVC 处理一个请求的流程
SpringMVC 作为一个基于请求-响应模型的框架,具有清晰的请求处理流程。下面详细介绍一个请求从接收到响应的完整流程:
请求处理流程概述
- 客户端发送请求:浏览器或其他客户端向服务器发送 HTTP 请求
- DispatcherServlet 接收请求:前端控制器接收所有的请求
- 处理器映射:确定由哪个 Controller 处理此请求
- 调用处理器:Controller 处理请求,生成模型数据
- 解析视图名:将逻辑视图名解析为实际视图对象
- 渲染视图:使用模型数据渲染视图
- 返回响应:将渲染后的视图返回给客户端
详细流程
Tomcat 接受到请求之后,会交给DispatcherServlet进行处理
- 当请求到达服务器后,Servlet 容器(如 Tomcat)根据 web.xml 配置或注解配置,将请求转发给 SpringMVC 的前端控制器 DispatcherServlet
- DispatcherServlet 作为整个 SpringMVC 的核心控制器,负责协调和组织不同组件处理请求
DispatcherServlet会根据URL路径找到对应的Handler
- DispatcherServlet 使用 HandlerMapping 来确定哪个 Controller 应该处理请求
- HandlerMapping 根据配置(如 @RequestMapping 注解)将请求 URL 映射到对应的 Controller 方法
- 在这个阶段,还会确定拦截器链(Interceptor Chain)
Handler就是加了@RequestMapping方法,通过反射来执行该方法
- Handler 是 Controller 中的具体处理方法,通常通过 @RequestMapping(或其变体如 @GetMapping, @PostMapping)注解标识
- DispatcherServlet 使用 HandlerAdapter 适配不同类型的处理器(Handler)
- HandlerAdapter 通过反射机制调用目标 Controller 方法
在执行方法之前会解析方法参数,比如解析@RequestParam,@RequestHeader,@PathVariable等注解
- SpringMVC 使用参数解析器(HandlerMethodArgumentResolver)解析控制器方法的参数
- 不同类型的参数和注解对应不同的解析策略
- 参数解析器从请求中提取数据,并转换为方法参数需要的类型
- 除了常见的 @RequestParam, @RequestHeader, @PathVariable,还支持 @RequestBody, @ModelAttribute 等
解析的过程就是从请求中获取相对应的数据,比如请求parameters,请求头,然后把数据传给对应的参数
- @RequestParam:从请求参数(query string 或 form data)中提取值
- @RequestHeader:从 HTTP 请求头中提取值
- @PathVariable:从 URL 路径变量中提取值
- @RequestBody:从请求体中解析 JSON/XML 并转换为 Java 对象
- 参数解析过程包括数据提取、类型转换和数据绑定
有了参数之后开始执行方法
- 所有必要的参数准备好后,通过反射调用 Controller 方法
- 方法执行过程中可能会调用 Service 层处理业务逻辑
- 可能会访问数据库或其他外部资源
- 方法执行可能会抛出异常,异常会被 SpringMVC 的异常处理机制捕获
方法执行后就会得到方法的返回值,SpringMVC会对返回值进行解析
- 根据方法返回值类型和注解,SpringMVC 决定如何处理结果
- 针对不同的返回值类型有不同的处理策略:
- 如果方法没有加@ResponseBody或者Controller不是@RestController,而返回值是字符串,那么会根据字符串去找对应的View视图
- 返回的字符串被视为逻辑视图名
- ViewResolver 将逻辑视图名解析为具体的 View 对象
- View 对象使用模型数据渲染最终输出
- 如果方法加了@ResponseBody,那么就把返回值直接返回给客户端,如果返回结果是对象类型,还会把对象转成JSON字符串
- 使用 HttpMessageConverter 将返回值转换为 HTTP 响应
- 对于对象类型,通常使用 Jackson 或 Gson 等库转换为 JSON
- 转换后的数据直接作为响应体返回客户端
- 如果方法没有加@ResponseBody或者Controller不是@RestController,而返回值是字符串,那么会根据字符串去找对应的View视图
响应生成并返回客户端
- 无论是视图渲染结果还是直接返回的数据,最终都被封装为 HTTP 响应
- 设置响应状态码、响应头和响应体
- DispatcherServlet 将响应返回给 Servlet 容器,再由容器返回给客户端
拦截器在请求处理流程中的位置
拦截器(Interceptor)可以在请求处理的不同阶段介入:
preHandle:在 Controller 方法执行前调用
- 返回 true 继续执行链,返回 false 中断执行
- 可用于权限检查、日志记录等
postHandle:在 Controller 方法执行后、视图渲染前调用
- 可以修改 ModelAndView
- 如果方法抛出异常则不会被调用
afterCompletion:在整个请求处理完成后调用
- 无论方法是否抛出异常都会被调用
- 通常用于清理资源
异常处理在请求流程中的位置
当处理过程中发生异常时:
- 首先检查是否有 @ExceptionHandler 方法处理异常
- 然后检查是否有 HandlerExceptionResolver 可以解析异常
- 如果都没有,异常会传播到 DispatcherServlet
- 最后可能会显示默认错误页面或返回错误状态码
总结
SpringMVC 的请求处理流程是一个精心设计的责任链,每个组件负责特定的功能:
- DispatcherServlet 作为中央控制器协调整个流程
- HandlerMapping 确定请求的处理器
- HandlerAdapter 适配不同类型的处理器
- 参数解析器解析方法参数
- 视图解析器和视图负责结果的渲染
理解这个流程有助于更好地使用 SpringMVC,处理常见问题,以及在必要时进行自定义扩展。